package com.github.shiqiyue.xm.filter;


import com.github.shiqiyue.xm.common.Result;
import com.github.shiqiyue.xm.common.ResultMsg;
import com.github.shiqiyue.xm.util.JsonUtils;
import com.github.shiqiyue.xm.util.ResponseUtils;
import com.github.shiqiyue.xm.util.SignUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/***
 * 签名过滤器
 * @author wenyao.wu
 * @date 2019/7/16
 */
@Slf4j
public class SignFilter extends OncePerRequestFilter {

    /***
     * appkey仓库
     */
    AppKeyStore appKeyStore;

    private AntPathMatcher antPathMatcher = new AntPathMatcher();
    /***
     * 不校验的链接地址
     */
    private List<String> ignorePathList = new ArrayList<>();
    /***
     * 校验的链接地址
     */
    private List<String> securePathList = new ArrayList<>();

    @Override
    protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
        try {
            String servletPath = httpServletRequest.getServletPath();
            for (String ignorePath : ignorePathList) {
                if (antPathMatcher.match(ignorePath, servletPath)) {
                    filterChain.doFilter(httpServletRequest, httpServletResponse);
                    return;
                }
            }
            boolean isNeedSecurity = false;
            for (String securePath : securePathList) {
                if (antPathMatcher.match(securePath, servletPath)) {
                    isNeedSecurity = true;
                    break;
                }
            }
            if(isNeedSecurity){
                filterChain.doFilter(httpServletRequest, httpServletResponse);
                return;
            }
            Object o = httpServletRequest.getParameter("sign");
            if (o == null) {
                log.error("缺少sign参数，path:{}", servletPath);
                ResponseUtils.populateResponse(ResponseEntity.ok(Result.fail(ResultMsg.REQUEST_ERROR)), httpServletResponse);
                return;
            }
            String paramSign = o.toString();
            Map<String, String> requestParam = getParameterMap(httpServletRequest);
            String appKey = requestParam.get("appkey");
            if (StringUtils.isEmpty(appKey)) {
                log.error("缺少appkey，path:{}", servletPath);
                ResponseUtils.populateResponse(ResponseEntity.ok(Result.fail(ResultMsg.REQUEST_ERROR)), httpServletResponse);
                return;
            }
            if (appKeyStore == null) {
                log.error("appkeyStore未设置");
                ResponseUtils.populateResponse(ResponseEntity.ok(Result.fail(ResultMsg.REQUEST_ERROR)), httpServletResponse);
                return;
            }
            String appSecret = appKeyStore.getAppSecretByAppkey(appKey);
            if (StringUtils.isEmpty(appSecret)) {
                log.error("appSecret未找到");
                ResponseUtils.populateResponse(ResponseEntity.ok(Result.fail(ResultMsg.REQUEST_ERROR)), httpServletResponse);
                return;
            }
            String sign = SignUtils.getMd5Sign(requestParam, appSecret);
            if (!paramSign.equals(sign)) {
                log.error("签名错误,appkey:{}, path:{}", appKey, servletPath);
                ResponseUtils.populateResponse(ResponseEntity.ok(Result.fail(ResultMsg.REQUEST_ERROR)), httpServletResponse);
                return;
            }
            filterChain.doFilter(httpServletRequest, httpServletResponse);
            return;
        } catch (Exception e) {
            log.error("timestamp filter 异常", e);
            ResponseUtils.populateResponse(ResponseEntity.ok(Result.fail(ResultMsg.REQUEST_ERROR)), httpServletResponse);
            return;
        }
    }

    /***
     * 添加不校验的链接地址
     * @param ignorePath
     */
    public SignFilter addIgnorePath(String ignorePath) {

        ignorePathList.add(ignorePath);
        return this;
    }

    /***
     * 添加校验的链接地址
     * @param securePath
     * @return
     */
    public SignFilter addSecurePath(String securePath) {
        securePathList.add(securePath);
        return this;
    }

    /***
     * 设置appkey仓库
     * @param appkeyStore
     * @return
     */
    public SignFilter setAppkeyStore(AppKeyStore appkeyStore) {
        this.appKeyStore = appkeyStore;
        return this;
    }

    public Map<String, String> getParameterMap(HttpServletRequest request) {
        Map<String, String[]> properties = request.getParameterMap();
        log.info("入参：{}", JsonUtils.beanToString(properties));
        // 返回值Map
        Map<String, String> returnMap = new HashMap(properties.size());
        for (String key : properties.keySet()) {
            String[] value = properties.get(key);
            if (value == null || value.length == 0) {
                returnMap.put(key, "");
                continue;
            }
            returnMap.put(key, value[0]);
        }
        return returnMap;
    }


    /***
     * appkey 仓库
     */
    public interface AppKeyStore {
        /***
         * 通过appkey获取appsecret
         * @param appkey
         * @return
         */
        String getAppSecretByAppkey(String appkey);
    }
}
